package dk.iha;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xmlpull.v1.XmlSerializer;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.RingtoneManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.util.Xml;

public class SensorLoggerService extends Service {

	SensorMain sensorMain = null;
	SensorLoggerDatabase sensorLoggerDatabase = null;
	String uniqueId = "";
	String emailAddress = "";
	String emailBody = "";
	MediaPlayer mediaPlayer = null;
	private boolean sendingMail = false;
	// State variable for enquiring about whether the service is running a
	// datacollection
	boolean isDataCollectionRunning = false;
	String baseFolder=null;
	static final String mailAddressXML = "emailAddress";
	static final String bodyXML = "body";
	static final String subjectXML = "subject";
	BluetoothDevice device;

	
	
	// Data interface exposed to the rest of the app (primarely the Activity)
	// STARTS
	/**
	 * Interface function that starts the datacollection
	 * 
	 * @return true if datacollection started
	 */
	public boolean startDataCollection() {
		if (!canStartDatacollection())
			return false;
		//SharedData.getInstance().addDebugDataLog_t("SensorLoggerService.startDataCollection");

		//gets the basefolder for this patient (folder name 0..19). basefolder has a trailing path seperator
		baseFolder = Utility.getFirstValidClientFolder();
		if(baseFolder == null){
			SharedData.getInstance().addDebugDataLog_t("startDataCollection: can not find a valid basefolder. Has 20 folder been created allready?");
			//delete first folder and try again
			List<String> folders = Utility.getAllClientFolders();
			if(folders.size() > 0)
				Utility.DeleteRecursive(folders.get(0));
			baseFolder = Utility.getFirstValidClientFolder();
			if(baseFolder == null){
				SharedData.getInstance().addDebugDataLog_t("startDataCollection: deleted first folder problem still exists?");
				//we cant do anything...
				return false;
			}
		}		
		
		//backup email address
		backupEmailAddress(emailAddress);
		
		// start the broadcastlistener
		logEvent.registerReceiver(this, onTimerHandler);
		// start the datalogging timer
		logEvent.startDataLoggingTimers(this);

		// Display a notification about us starting. We put an icon in the
		// status bar.
		showNotification();

		// Initialise sensors
		sensorMain = new SensorMain();
		//gpssensor = new GPSSensor(this);
		//gpssensor = null;
		sensorMain.Initialize(this, uniqueId, sensorLoggerDatabase,	onSensorCompleteHandler, baseFolder, device);
		isDataCollectionRunning = true;
		//signal UI that service state changed
		sendServiceStateChangedBroadcast();
		return true;
	}

	public boolean canStartDatacollection() {
		// check if datacollection is allready running
		if (isDataCollectionRunning() == true)
			return false;
		
		// service is currently running the sendmail thread
		if (true == sendingMail)
			return false;
		
		//check if GPS is enabled
//		if(!SharedData.isGPSEnabled(this))
//			return false;
		return true;
	}

	public boolean isDataCollectionRunning() {
		return isDataCollectionRunning;
	}

	private void sendServiceStateChangedBroadcast() {
		Intent intent = new Intent();
		intent.setAction(SharedPreferences.BROADCAST_MESSAGE_SERVICE_STATE_CHANGED);
		sendBroadcast(intent);
	}


	public boolean isNetworkAvailable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(SensorLoggerActivity.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
		return activeNetworkInfo != null;
	}

	/**
	 * Stops the datacollection
	 */
	public void stopDataCollection() {
		Log.w("WL", "stopDataCollection starts");
		isDataCollectionRunning = false;

		// stop the datalogging timers
		logEvent.stopDataLoggingTimers(this);
		// Unregister broadcast receivers
		logEvent.unRegisterReceiver(this);

		sensorMain.externalStop();
		sensorMain = null;
		
		
		//Write data to baseFolder
		List<LogItem> logItems = getLoggedDataFromDB();
		// write xml
		if(!writeMailtoXML(createMailContent(logItems), baseFolder+SharedPreferences.EMAIL_XML_FILE)){
			SharedData.getInstance().addDebugDataLog_t("writeMailtoXML failed! for folder:"+baseFolder);
		}
		// write data.csv
		if(!writeDataToSDCard(logItems, baseFolder)){
			SharedData.getInstance().addDebugDataLog_t("writeDataToSDCard failed! for folder:"+baseFolder);
		}
		
		
		if(isNetworkAvailable()){
			//SharedData.getInstance().addDebugDataLog_t("network available");
			//sendMailInBackground();
			sendClientData(true);
		}
		//if no network - just save to SD card
		else{

			SharedData.getInstance().addDebugDataLog_t("network NOT available - data saved to SD card");
			//signal that we are finished working her in the Service
			preExitHandler.handleMessage(new Message());
			//writeDataToSDCard(getLoggedDataFromDB());			
		}
		
		sendServiceStateChangedBroadcast();

		//SharedData.getInstance().addDebugDataLog_t("SensorLoggerService.stopDataCollection");
		
		Log.w("WL", "stopDataCollection stops");
	}
	
	/**
	 * Gets data from the dB for the current user and deletes data in dB afterwards
	 * @return
	 */
	private List<LogItem> getLoggedDataFromDB(){
		List<LogItem> items = sensorLoggerDatabase.getLogItemsbyUniquename(getUniqueId());
		if(items.size() > 0){
			sensorLoggerDatabase.deleteLogItemsWithUniqueId(uniqueId);
		}		
		return items;
	}
	
	private boolean writeDataToSDCard(List<LogItem> items, String filelocation){
		String data = "";
		for (LogItem item : items) {
			data += item.toString();
		}		
		return Utility.writeFile(filelocation, SharedPreferences.FILENAME, data, false /* create new file allways */);
	}

	
	
	boolean isDataCollectionComplete;
	/**
	 * Sends data situated in the application folder in folders 0..19
	 * @param isDataCollectionComplete_ true if we are done collecting data and needs to shut down after sendClientData completes
	 */
	private void sendClientData(boolean isDataCollectionComplete_) {
		// This moves the time consuming operation to a child thread.
		isDataCollectionComplete = isDataCollectionComplete_;
		sendingMail = true;
		sendServiceStateChangedBroadcast();
		Thread thread = new Thread(null, doSendClientDataThread, "sendingMail");
		thread.start();
	}
	private Runnable doSendClientDataThread = new Runnable() {
		public void run() {
			//run trough all folders named 0..19 and check i
			List<String> folders = Utility.getAllClientFolders();
			for(String folder : folders){
				//process and send data in 'folder'
				MailContent mailCnt = readMailXML(folder+SharedPreferences.EMAIL_XML_FILE);
				if(mailCnt == null){
					//malformed xml file. Only way to handle this is to delete folder
					Utility.DeleteRecursive(folder);
					continue;
				}
				if(!sendMail(mailCnt, folder)){
					//we cant send the mail
					Utility.DeleteRecursive(folder);
					continue;
				}
				//We have successfully sent the mail from 'folder' now delete the folder 
				Utility.DeleteRecursive(folder);
			}
			
			//send a message to the caller when we are done sending mail
			mailSentHandler.dispatchMessage(new Message());
			if(isDataCollectionComplete)
				preExitHandler.dispatchMessage(new Message());
		}
	};
	
	private boolean sendMail(MailContent mailContent, String folder) {
		boolean success = true;
		MailService mail = new MailService(SharedPreferences.EMAIL_ADDRESS,	SharedPreferences.EMAIL_PASSWORD);
		String[] toArr = { mailContent.emailAddress };
		mail.setTo(toArr);
		mail.setFrom(SharedPreferences.EMAIL_ADDRESS);
		mail.setSubject(mailContent.subject);
		mail.setBody(mailContent.body);
		
		try {
			//TODO 2*filename???
			mail.addAttachment(folder + SharedPreferences.FILENAME, SharedPreferences.FILENAME);
			mail.addAttachment(folder + SharedPreferences.RAW_DATA_FILENAME, SharedPreferences.RAW_DATA_FILENAME);
			if (mail.send()) {
				SharedData.getInstance().addDebugDataLog_t("EMAIL SENT");
			}

		} catch (Exception e) {
			e.printStackTrace();
			success = false;
		}
		return success;
	}


	

	class MailContent{
		public String emailAddress = null;
		public String subject = null;
		public String body = null;
	};
	
	/**
	 * Writes mail content to an XML file
	 * @param cnt
	 * @param fileName
	 * @return
	 */
	boolean writeMailtoXML(MailContent cnt, String fileName){
		
        File newxmlfile = new File(fileName);
        try{
            newxmlfile.createNewFile();
        }catch(IOException e)
        {
        	SharedData.getInstance().addDebugDataLog_t("Exception in create new File");
            return false;
        }
        FileOutputStream fileos = null;
        try{
            fileos = new FileOutputStream(newxmlfile);

        }catch(FileNotFoundException e)
        {
        	SharedData.getInstance().addDebugDataLog_t(e.toString());
            return false;
        }

		XmlSerializer serializer = Xml.newSerializer();
        try{
	        serializer.setOutput(fileos, "UTF-8");
	        serializer.startDocument(null, Boolean.valueOf(true));
	        //serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
	        serializer.startTag(null, "client");

	        serializer.startTag(null, mailAddressXML);
	        serializer.text(cnt.emailAddress);
	        serializer.endTag(null, mailAddressXML);
	        
	        serializer.startTag(null, subjectXML);
	        serializer.text(cnt.subject);
	        serializer.endTag(null, subjectXML);
	        
	        serializer.startTag(null, bodyXML);
	        serializer.text(cnt.body);
	        serializer.endTag(null,bodyXML);
	        serializer.endTag(null,"client");
	        serializer.endDocument();
	        serializer.flush();
	        fileos.close();
        }catch(Exception e)
        {
        	SharedData.getInstance().addDebugDataLog_t("Exception occured in writing xml file");
            return false;
        }
        return true;
	}
	/**
	 * Reads the content from a mail content XML file
	 * @param fileName
	 * @return
	 */
	MailContent readMailXML(String fileName){
		MailContent mailContent = new MailContent();
		File xmlfile = new File(fileName);
		Document doc;     
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			dbf.setNamespaceAware(false);
			dbf.setValidating(false);
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(xmlfile);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		Node root = doc.getFirstChild();
		if(root == null){
			return null;
		}
		Node childNode;
		for (Node child = root.getFirstChild(); child != null ; child = child.getNextSibling()) {
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				if (child.getNodeName().equals( subjectXML )) {
					childNode = child.getFirstChild();
					if(childNode == null)
						return null;
					mailContent.subject = childNode.getNodeValue(); 
				}
				else if (child.getNodeName().equals( mailAddressXML )) {
					childNode = child.getFirstChild();
					if(childNode == null)
						return null;
					mailContent.emailAddress = childNode.getNodeValue(); 
				}
				else if (child.getNodeName().equals( bodyXML )) {
					childNode = child.getFirstChild();
					if(childNode == null)
						return null;
					mailContent.body = childNode.getNodeValue(); 
				}
			}
		}
		if(mailContent.subject == null || mailContent.body == null || mailContent.emailAddress == null){
			SharedData.getInstance().addDebugDataLog_t("ERROR: readMailXML: Subject, body or emailAddress is null!");
			return null;
		}
		return mailContent;
	}	
	
	
	private MailContent createMailContent(List<LogItem> dBitems){
		MailContent cnt = new MailContent();
		//Create email content/body
		cnt.body = createEmailBody(dBitems);
		
		cnt.emailAddress = getEmailAddress();
		cnt.subject = SharedPreferences.EMAIL_SUBJECT + getUniqueId();
		return cnt;
	}
	

	private String createEmailBody(List<LogItem> logitems) {
		String startDate = "";
		String startTime = "";
		String endDate = "";
		String endTime = "";
		if(logitems.size()>0){
			endDate = DateFormating.getTimeInFormat(logitems.get(0).getLogTime(), DateFormating.DAYYEARFORMAT);
			endTime = DateFormating.getTimeInFormat(logitems.get(0).getLogTime(), DateFormating.HOURMINUTEFORMAT);
			startDate = DateFormating.getTimeInFormat(logitems.get(logitems.size()-1).getLogTime(), DateFormating.DAYYEARFORMAT);
			startTime = DateFormating.getTimeInFormat(logitems.get(logitems.size()-1).getLogTime(), DateFormating.HOURMINUTEFORMAT);
		}
		StringBuilder emailText = new StringBuilder(); 
		emailText.append("Hi you have just received the following results from the Adherence Logger\n\n");
		emailText.append("Patient id: " + uniqueId + "\n");
		emailText.append("Start date: " + startDate + " Start time: " + startTime + "\n");
		emailText.append("End date: " + endDate + " End time: " + endTime + "\n");
		emailText.append("Email sent to: " + emailAddress + "\n\n");
		emailText.append("The table below shows your movement for the past 24 hours\n");
		String movement = createMovementData(logitems);
		emailText.append(movement);
		emailText.append("Click on below link for map view of your movement for the past 24 hours:\n");
		URL url = createURL(logitems);
		emailText.append(url.toString());
		return emailText.toString();
	}
	
	private String createMovementData(List<LogItem> logitems){
		StringBuilder movement = new StringBuilder();
		movement.append("Time   Battery  Movement  Temperature  Position\n");
		for(LogItem logitem:logitems){
			movement.append(DateFormating.getTimeInFormat(logitem.getLogTime(), DateFormating.HOURMINUTEFORMAT)  + "  " +
							logitem.getBatteryLevel() + "          " +
							logitem.getMovement() + "\t\t  " + 
							logitem.gettemperature() + "\t\t   " + 
							logitem.getLatitude()+","+logitem.getLongitude()+"\n");
		}
		movement.append("\n");
		return movement.toString();				
	}

	/**
	 * Creates the URL containing the GPS positions
	 * @param logitems
	 * @return
	 */
	private URL createURL(List<LogItem> logitems) {
		String urlAsString = "";
		URL url = null;
		List<String> markers = new ArrayList<String>();
		String [] label = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
		int labelIndex = 0;
		for (int i = 0; i < logitems.size() ; i++) {
			String latitude = logitems.get(i).getLatitude();
			String longitude = logitems.get(i).getLongitude();
			if (!latitude.equalsIgnoreCase(SharedPreferences.NOT_AVAILABLE)&& 
				!longitude.equalsIgnoreCase(SharedPreferences.NOT_AVAILABLE)&&
				!latitude.equalsIgnoreCase("0") && 
				!longitude.equalsIgnoreCase("0")) {
				if(labelIndex < label.length)
					markers.add("&markers=color:blue%7Clabel:" + label[labelIndex++] + "%7C" + latitude + "," + longitude);
			}
		}
		//Initial part of url
		urlAsString = "http://maps.googleapis.com/maps/api/staticmap?";
		urlAsString += "&zoom=auto&size=800x600&maptype=roadmap";
		//Now add all of the logged coordinates
		for (String marker : markers) {
			urlAsString += marker;
		}
		//last part of url
		urlAsString += "&sensor=false";
		try {
			url = new URL(urlAsString);

		} catch (MalformedURLException e) {
			e.printStackTrace();
		}		
		return url;
	}
	
//	private List<LogItem> dummyPosition(){
//		List<LogItem> list = new ArrayList<LogItem>();
//		list.add(new LogItem("1","11:12","movement","56.17214933633902","10.19106388092041", ""));
//		list.add(new LogItem("2","11:12","movement","56.18214933633902","10.19106388092041", ""));
//		list.add(new LogItem("3","11:12","movement","56.19214933633902","10.19106388092041", ""));
//		list.add(new LogItem("4","11:12","movement","56.20214933633902","10.19106388092041", ""));
//		list.add(new LogItem("5","11:12","movement","56.16214933633902","10.19106388092041", ""));
//		list.add(new LogItem("6","11:12","movement","56.15214933633902","10.19106388092041", ""));
//		list.add(new LogItem("7","11:12","movement","56.14214933633902","10.19106388092041", ""));
//		list.add(new LogItem("8","11:12","movement","56.13214933633902","10.19106388092041", ""));
//		list.add(new LogItem("9","11:12","movement","56.12214933633902","10.19106388092041", ""));
//		list.add(new LogItem("10","11:12","movement","56.11214933633902","10.19106388092041", ""));
//		list.add(new LogItem("11","11:12","movement","56.10214933633902","10.19106388092041", ""));
//		list.add(new LogItem("12","11:12","movement","56.17214933633902","10.18106388092041", ""));
//		list.add(new LogItem("13","11:12","movement","56.17214933633902","10.17106388092041", ""));
//		list.add(new LogItem("14","11:12","movement","56.17214933633902","10.16106388092041", ""));
//		list.add(new LogItem("15","11:12","movement","56.17214933633902","10.15106388092041", ""));
//		list.add(new LogItem("16","11:12","movement","56.17214933633902","10.14106388092041", ""));
//		list.add(new LogItem("17","11:12","movement","56.17214933633902","10.13106388092041", ""));
//		list.add(new LogItem("18","11:12","movement","56.17214933633902","10.12106388092041", ""));
//		list.add(new LogItem("19","11:12","movement","56.17214933633902","10.11106388092041", ""));
//		list.add(new LogItem("20","11:12","movement","56.17214933633902","10.10106388092041", ""));
//		list.add(new LogItem("21","11:12","movement","56.17214933633902","10.09106388092041", ""));
//		list.add(new LogItem("22","11:12","movement","56.17214933633902","10.08106388092041", ""));
//		list.add(new LogItem("23","11:12","movement","56.17214933633902","10.07106388092041", ""));
//		list.add(new LogItem("24","11:12","movement","56.17214933633902","10.06106388092041", ""));
//		list.add(new LogItem("25","11:12","movement","56.17214933633902","10.05106388092041", ""));
//		list.add(new LogItem("26","11:12","movement","56.17214933633902","10.04106388092041", ""));
//		return list;
//	}

	LogEvent logEvent = new LogEvent();

	@Override
	public void onCreate() {
		super.onCreate();
		// initialise the db
		sensorLoggerDatabase = new SensorLoggerDatabase(this);

		//restore the email address
		emailAddress = restoreEmailAddress();
		if(emailAddress == null)
			emailAddress = "";
		sendServiceStateChangedBroadcast();
		
		//If any unsent data exists on the phone try to send them
		if(Utility.getAllClientFolders().size() > 0 && isNetworkAvailable()){
			SharedData.getInstance().addDebugDataLog_t("onCreate: data is available on phone and network is available. sending data...");
			//sendMailInBackground();
			sendClientData(false);
		}
	}

	@Override
	public void onDestroy() {
		 Log.w("WL", "SensorLoggerService.onDestroy");
		sensorLoggerDatabase.closeDatabase();
		sensorLoggerDatabase = null;
		super.onDestroy();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.w("LIFETIME", "onStartCommand");
		return Service.START_STICKY;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// Log.w("LIFETIME", "SensorLoggerService.onUnbind");
		return super.onUnbind(intent);
	}

	// bind this service together with an activity
	// har vi bruge for en serviceConnection i vores Activity??
	@Override
	public IBinder onBind(Intent intent) {
		// Log.w("LIFETIME", "SensorLoggerService.onBind");
		return binder;
	}

	public long getMeasurementInterval() {
		return SharedPreferences.SAMPLE_INTERVAL_PERIOD;
	}

	public String getUniqueId() {
		return uniqueId;
	}

	public void setUniqueId(String uniqueId) {
		this.uniqueId = uniqueId;
	}

	public String getEmailAddress() {
		return emailAddress;
	}

	public void setBluetoothDevice(BluetoothDevice dev){
		device = dev;
	}
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}
	
	private void backupEmailAddress(String email){
		Utility.writeFile(SharedData.getFilePath(), SharedPreferences.EMAIL_ADDRESS_FILE_NAME, email, false /*create new file*/);
	}
	private String restoreEmailAddress(){

		//Get the text file
		File file = new File(SharedData.getFilePath(), SharedPreferences.EMAIL_ADDRESS_FILE_NAME);

		//Read text from file
		String address = "";
		try {
			BufferedReader br = new BufferedReader(new FileReader(file));
			for(;true;){
				int character = br.read();
				if(character == -1)
					break;
				address += (char)character;
			}
			br.close();
		}
		catch (IOException e) {
		    //You'll need to add proper error handling here
			return null;
		}		
		
		return address;
		
		
		
//		String address = "";
//		InputStream is;
//		try {
//			String file = SharedData.getFilePath() + File.separator +  SharedPreferences.EMAIL_ADDRESS_FILE_NAME;
//			is = openFileInput(file);
//			int character=0;
//			while (true)
//			{
//				character = is.read();
//				if(character == -1)
//					break;
//				address += (char)character;
//			}
//			is.close();		
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//			return null;
//		}
//		return address;
	}

	/*
	 * Helper class for service
	 */
	public class MyBinder extends Binder {
		SensorLoggerService getService() {
			return SensorLoggerService.this;
		}
	}

	private final IBinder binder = new MyBinder(); 

	/**
	 * Sets this service back from Foreground (meaning: this service CAN be
	 * killed by Android)
	 */
	private void hideNotification() {
		stopForeground(true);
	}

	/**
	 * Handler for our mail sent background thread
	 * Guaranteed to be called before the service closes
	 */
	Handler mailSentHandler = new Handler() {
		public void handleMessage(Message msg) {
			// Mail has been sent
			sendingMail = false;
			sendServiceStateChangedBroadcast();
			// make service "not foreground". This reduces priority of service
			Log.w("WL", "MailSent handler");
		};
	};

	/**
	 * Handler for end of app
	 * Must be called when sending mail and datacollection is completed
	 */
	Handler preExitHandler = new Handler() {
		public void handleMessage(Message msg) {
			// Mail has been sent
			sendServiceStateChangedBroadcast();
			// make service "not foreground". This reduces priority of service
			hideNotification();
			AlarmAlertWakeLock.releaseCpuLock();

			if(SharedPreferences.DEBUG){
				playSound(SensorLoggerService.this, PlaySound.Notification);
			}

			SensorLoggerService.this.stopSelf();
		};
	};
	
	
	/**
	 * Called when a sensor has stopped processing
	 * Called for each implemented sensor
	 * if stopDataCollection() is currently running => onSensorCompleteHandler.handleMessage should not release WakeLock
	 */
	Handler onSensorCompleteHandler = new Handler() {
		public void handleMessage(Message msg) {
			// release the AlarmAlertWakeLock as sensor measurement has
			// finished.
			Log.w("WL", "SensorComplete Handler");

			if(SharedPreferences.DEBUG){
				playSound(SensorLoggerService.this, PlaySound.BeepBeep);
			}
			//isDataCollectionRunning() is true when we are doing the samplings in this case we should releaseCPULock
			//isDataCollectionRunning() is false when we are finished sampling. In this case we should NOT releaseCPULock. CPULock will be released by after we have sent a mail.
			if(isDataCollectionRunning())
				AlarmAlertWakeLock.releaseCpuLock();
			//SharedData.getInstance().addDebugDataLog_t("onSensorCompleteHandler called");
		};
	};

	/**
	 * Handler for our AlarmManager timer 
	 * The AlarmManager requires that we release the OnReceive handler 
	 * rather quickly so the OnReceive posts an
	 * async message here instead
	 */
	Handler onTimerHandler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.obj.toString().equals(SharedPreferences.BROADCAST_MESSAGE_TIMEOUT_TOTAL_LOGGING_PERIOD)) {
				//the complete logging interval has elapsed
				Log.w("WL", "handleMessage TOTAL_LOGGING starts");
				stopDataCollection();
				Log.w("WL", "handleMessage TOTAL_LOGGING ends");
			} else if (msg.obj.toString().equals(SharedPreferences.BROADCAST_MESSAGE_TIMEOUT_SAMPLE_INTERVAL_PERIOD)) {
				//The sample interval has elepsed - prepare another sample
				Log.w("WL", "handleMessage SAMPLE_INTERVAL starts");
				//do play sound

				if(SharedPreferences.DEBUG){
					SensorLoggerService.this.playSound(SensorLoggerService.this, PlaySound.Beep);		
				}

				sensorMain.startDataCollection();
				//Log.w("WL", "handleMessage SAMPLE_INTERVAL ends");
			} else {
				assert (false);
			}
		};
	};

	/**
	 * Makes this an foreground service (meaning: this service will no be killed
	 * by Android)
	 */
	private void showNotification() {
		// Log.w("USER", "MainService.showNotification");
		int NOTIFICATION_ID = 1;

		// Create an Intent that will open the main Activity if the notification
		// is clicked.
		Intent intent = new Intent(this, SensorLoggerActivity.class);
		PendingIntent pi = PendingIntent.getActivity(this, 0, intent,
				PendingIntent.FLAG_CANCEL_CURRENT);

		// Set the Notification UI parameters
		Notification notification = new Notification(
				R.drawable.healthlogger_icon, getString(R.string.app_name),
				System.currentTimeMillis());
		notification.setLatestEventInfo(this, getString(R.string.app_name),
				"Show user interface...", pi);

		// Set the Notification as ongoing
		notification.flags = notification.flags
				| Notification.FLAG_ONGOING_EVENT;

		// Move the Service to the Foreground
		startForeground(NOTIFICATION_ID, notification);
	}

	// play sound
	enum PlaySound {Notification, Beep, BeepBeep};
	public void playSound(Context context, PlaySound sound) {
		try {
			mediaPlayer = new MediaPlayer();
			
			if(sound == PlaySound.Notification){
				Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
				mediaPlayer.setDataSource(context, soundUri);
			}
			else{
				Resources res = getResources();
				AssetFileDescriptor afd = res.openRawResourceFd( sound == PlaySound.Beep ? R.raw.beep : R.raw.beep_beep);
				mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
			}
			
			final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
			if (audioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION) != 0) {
				mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
				mediaPlayer.setLooping(false);
				mediaPlayer.prepare();
				mediaPlayer.start();
			}
			mediaPlayer
					.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

						public void onCompletion(MediaPlayer mp) {
							mp.release();
							mediaPlayer = null;
							// Log.w("USERDATA","mMediaPlayer.setOnCompletionListener");
						}

					});

		} catch (IllegalArgumentException e) {

		} catch (SecurityException e) {

		} catch (IllegalStateException e) {

		} catch (IOException e) {

		}
	}
	
}
